#!/usr/bin/env python2
#-*- coding: utf-8 -*-

import json
import datetime

from sqlalchemy.orm import class_mapper
# from sqlalchemy.ext.declarative.api import DeclarativeMeta


def _column_json_loads(obj, col):
    _column_val = getattr(obj, col.name)
    if str(col.type) == 'TEXT' or str(col.type).startswith('VARCHAR'):
        _column_val = _try_json_loads(_column_val)
    return _column_val


def _try_json_loads(val):
    try:
        val = json.loads(val)
    except Exception,e:
        pass
    return val


def sqlalchemy_obj_to_dict(obj, is_sql_obj=True):
    # TODO
    if hasattr(obj, 'dump'):
        res = obj.dump()
        return res
        # return object2dict(res)
    else:
        dict_result = {}
        fields = []
        relationships = []
        if is_sql_obj:
            dict_result = dict((col.name, _column_json_loads(obj, col))
                for col in class_mapper(obj.__class__).mapped_table.c)

            fields = ( col.name for col in class_mapper(obj.__class__).mapped_table.c )
            relationships = class_mapper(obj.__class__).relationships.keys()
        for d in dir(obj):
            if d.startswith('_') | d.startswith('metadata'):
                continue
            elif d in fields or d in relationships:
                continue
            else:
                key = '%s' %(d)
                val = getattr(obj, d)
                if callable(val):
                    continue
                dict_result[key] = val
        return dict_result


def object2dict(dbresult, level=1):
    # TODO import
    from Ump.objs.db.models import UssBase

    if isinstance(dbresult, UssBase):
        dbresult = sqlalchemy_obj_to_dict(dbresult)
    elif isinstance(dbresult, list):
        dbresult = [object2dict(x, level=level+1) for x in dbresult]
    elif isinstance(dbresult, dict):
        for k, v in dbresult.iteritems():
            dbresult[k] = object2dict(v, level=level+1)
    else:
        pass
    return dbresult


class DateEncoder(json.JSONEncoder):

    def default(self, obj):
        # TODO import
        from Ump.objs.db.models import UssBase, db

        from Ump.umptypes import UmpPath
        from Ump import BaseFilterQuery

        # print '--- dumps', type(obj), isinstance(obj, Base), obj
        if isinstance(obj, datetime.datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, datetime.date):
            return obj.strftime('%Y-%m-%d')
        elif isinstance(obj, UmpPath):
            return str(obj)
        elif isinstance(obj, BaseFilterQuery):
            return str(obj)
        elif isinstance(obj, UssBase):
            return sqlalchemy_obj_to_dict(obj)
        else:
            return json.JSONEncoder.default(self, obj)


def data2json(obj):
    result = json.dumps(obj, cls=DateEncoder)
    return result
